package com.xdf.whiteaccount.service.impl;

import com.xdf.whiteaccount.entity.Jrkbillsum;
import com.xdf.whiteaccount.exception.BusinessException;
import com.xdf.whiteaccount.service.CallService;
import com.xdf.whiteaccount.service.JrkbillsumService;
import com.xdf.whiteaccount.service.base.BaseService;
import com.xdf.whiteaccount.utils.Example;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xdf.whiteaccount.entity.ProductOutwardOrder;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import com.xdf.whiteaccount.dao.ProductOutwardOrderMapper;
import com.xdf.whiteaccount.service.ProductOutwardOrderService;

/**
 * @Description : com.xdf.whiteaccount.service.impl(业务层实现类,该类为生成器自动生成).
 * @Author : 张柯
 * @Date : 2021-07-02 17:20:51
 */
@Service
public class ProductOutwardOrderServiceImpl extends BaseService implements ProductOutwardOrderService {
    @Autowired
    private ProductOutwardOrderMapper dao;
    @Autowired
    private CallService callService;
    @Autowired
    private JrkbillsumService jrkbillsumService;

    /**
     * @Describe 新增方法
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(ProductOutwardOrder record) throws Exception {
        int res = dao.insert(record);
        if (record.getIsSendDirectly() && record.getStorageId() == null) {
            ProductOutwardOrder copy = (ProductOutwardOrder) record.clone();
            copy.setOrderCode(callService.productOutwardOrderCodeGen(false));
            copy.setLinkedOrderCode(record.getOrderCode());
            copy.setId(null);
            res += dao.insert(copy);
        }
        return res;
    }

    /**
     * @Describe 选择新增
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSelective(ProductOutwardOrder record) throws Exception {
        int res = dao.insertSelective(record);
        if (record.getIsSendDirectly() && record.getStorageId() == null) {
            ProductOutwardOrder copy = (ProductOutwardOrder) record.clone();
            copy.setOrderCode(callService.productOutwardOrderCodeGen(false));
            copy.setLinkedOrderCode(record.getOrderCode());
            copy.setId(null);
            res += dao.insertSelective(copy);
        }
        return res;
    }

    /**
     * @Describe 批量新增
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiInsert(List<ProductOutwardOrder> list) throws Exception {
        return dao.multiInsert(list);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKey(ProductOutwardOrder record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 选择修改
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKeySelective(ProductOutwardOrder record) throws Exception {
        return dao.updateByPrimaryKeySelective(record);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(ProductOutwardOrder record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 批量修改
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiUpdate(List<ProductOutwardOrder> list) throws Exception {
        return dao.multiUpdate(list);
    }

    /**
     * @Describe 根据主键查询
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    public ProductOutwardOrder selectByPrimaryKey(Long id) throws Exception {
        return dao.selectByPrimaryKey(id);
    }

    /**
     * 2021年8月22日 14:07:58 chanchaw
     * 删除时如果有关联的打卷数据，则清空对应的标记：jrkbillsum.imported 设置为0
     * @Describe 根据主键删除
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByPrimaryKey(Long id) throws Exception {
        Assert.notNull(id<=0,"传入了非法主键，无法删除！");
        Assert.state(id<=0,"传入了非法主键，无法删除！");
        ProductOutwardOrder productOutwardOrder = selectByPrimaryKey(id);
        Assert.notNull(productOutwardOrder,"未找到主键" + id + "的数据，无法删除！");

        // 查询获取对应的 jrkbillsum 的主键，修改已导入的状态
        Integer jrkId = Optional.ofNullable(productOutwardOrder.getJrkid()).orElse(0);
        updateJrkImported(jrkId,0);

        return dao.deleteByPrimaryKey(id);
    }

    /**
     * 根据主键作废
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelByPk(Long id) throws Exception {
        if (id == null) id = 0L;
        ProductOutwardOrder productOutwardOrder = Optional.ofNullable(selectByPrimaryKey(id)).orElse(new ProductOutwardOrder());
        Integer jrkid = Optional.ofNullable(productOutwardOrder.getJrkid()).orElse(0);
        updateJrkImported(jrkid,0);
        return dao.updateByPrimaryKeySelective(ProductOutwardOrder.builder().id(id).state(0).build());
    }

    /**
     * 根据主键审核
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int auditById(Long[] id) throws Exception {
        return dao.updateByExampleSelective(ProductOutwardOrder.builder().isAudit(true).auditUserId(getLoginUserId()).build(), new Example().andIn("id", id));
    }

    /**
     * 根据主键取消审核
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelAuditById(Long[] id) throws Exception {
        return dao.updateByExampleSelective(ProductOutwardOrder.builder().isAudit(false).auditUserId(0).build(), new Example().andIn("id", id));
    }

    /**
     * @Describe 根据Entity查询
     * @author 张柯
     * @Date 2021-07-02 17:20:51
     */
    @Override
    public List<ProductOutwardOrder> listQuery(ProductOutwardOrder record) throws Exception {
        return dao.selectByParam(record);
    }

    @Override
    public List<ProductOutwardOrder> gatherByJrk(List<Long> jrkIds) {
        return dao.gatherByJrk(jrkIds);
    }

    /**
     * 2021年8月20日 10:59:05 chanchaw
     * 传入打卷表 jrkbillsum 的主键（集合），将这些数据按照计划单、原料批号汇总
     * 汇总后的数据自动生成 ProductOutwardOrder 的一条数据
     * 同时将 ProductOutwardOrder.id 回写入 jrkbillsum.outwardid
     * 打卷触摸屏上在更改已入库数据（更换计划）时会提示要求删除对应的已导入数据
     * 该动作要用到上面的关联，删除已导入数据后要求用户再次手动导入外发坯布入库数据
     * @param jrkIds jrkbillsum.id
     * @param processCompanyName 加工户
     * @return 写入外发坯布入库的行数
     */
    @Transactional
    @Override
    public int insertByGatheredJrk(List<Long> jrkIds,String processCompanyName) {
        Assert.notEmpty( jrkIds,"没有传入有效主键，无法生成坯布入库！" );
        Assert.hasLength(processCompanyName,"没有传入加工户名称，无法生成坯布入库！");

        // 2021年8月20日 10:11:23 chanchaw
        // 根据打卷表 jrkbillsum 的主键查询获取的汇总数据，按照计划单编号、批次号等
        // 遍历时写入单据日期和加工户
        List<ProductOutwardOrder> list = gatherByJrk(jrkIds);

        for (int i = 0; i < list.size(); i++) {
            ProductOutwardOrder item = list.get(i);
            Date orderDate = new Date();
            item.setOrderDate(orderDate);// 设置单据日期
            item.setProcessCompany(processCompanyName);// 设置加工户名称
            item.setCreateUserId(getLoginUserId());// 设置当前登录的用户ID

            // 设置单据编号
            String orderCode = callService.productOutwardOrderCodeGen(false);
            item.setOrderCode(orderCode);

            try {
                insertSelective(item);
                // 生成一个外发入库数据立即更新关联的打卷数据的外键：jrkbillsum.outwardid
                jrkbillsumService.multiUpdateOutwardId(item);
            } catch (Exception e) {
                throw new BusinessException("新增坯布入库时出现异常！");
            }
        }

        return list.size();
    }

    /**
     * 2021年8月21日 16:54:29 chanchaw
     * 修改之前的设计了，之前是将打卷数据按照计划单主键汇总后导入
     * 现在是根据打卷数据一对一导入
     * @param jrkIds
     * @return
     */
    @Override
    public int mapping8jrk(List<Long> jrkIds,String processCompanyName) {
        Assert.notEmpty( jrkIds,"没有传入有效主键，无法生成坯布入库！" );
        Assert.hasLength(processCompanyName,"没有传入加工户名称，无法生成坯布入库！");
        // 将表 jrkbillsum 数据通过SQL映射为 product_outward_order 数据时将 jrkbillsum.id 映射到 product_outward_order.jrkid
        List<ProductOutwardOrder> list = dao.mapping8jrk(jrkIds);


        for (int i = 0; i < list.size(); i++) {
            ProductOutwardOrder item = list.get(i);
            Date orderDate = new Date();
            item.setOrderDate(orderDate);// 设置单据日期
            item.setProcessCompany(processCompanyName);// 设置加工户名称
            item.setCreateUserId(getLoginUserId());// 设置当前登录的用户ID
            item.setMode("自动导入");

            // 设置单据编号,true 表示打卷后的白坯，false 表示未剖幅的
            String orderCode = callService.productOutwardOrderCodeGen(true);
            item.setOrderCode(orderCode);

            try {
                insertSelective(item);// 向表 product_outward_order 写入数据 - 外发入库

                // 更新对应的打卷数据，标记为已导入状态
                Jrkbillsum jrk = new Jrkbillsum();
                jrk.setId(item.getJrkid());
                jrk.setImported(1);
                jrkbillsumService.updateByPrimaryKeySelective(jrk);
            } catch (Exception e) {
                throw new BusinessException("新增坯布入库时出现异常！");
            }
        }

        return list.size();
    }

    /**
     * 2021年8月22日 14:13:55 chanchaw
     * 修改制定打卷数据是否已导入的状态
     * @param jrkid
     * @param imported
     * @return
     */
    private int updateJrkImported(Integer jrkid,Integer imported) throws Exception {
        Jrkbillsum jrk = new Jrkbillsum();
        jrk.setId(jrkid);
        jrk.setImported(imported);
        return jrkbillsumService.updateByPrimaryKeySelective(jrk);
    }

}